package cn.chencq.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class ReflectTest {

    public String getNameByClass() {
        String name = "";
        System.out.println("通过类本身获得对象,从而获得类名");
        Class tclass = this.getClass();
        name = tclass.getName();
        return name;
    }

    public String getSuperClassBySubClass() {
        String name = "";
        System.out.println("通过类对象获得父类");
        Class subClass = this.getClass();
        Class superClass = subClass.getSuperclass();
        name = superClass.getName();
        return name;
    }

    public String getClassByClassName(String className) {
        Class obj = null;
        try {
            obj = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj.getName();
    }

    // 获得类所有的属性
    public void getFieldNames(String className) {
        Class c;
        try {
            c = Class.forName(className);
            // getFields 获取的是public属性
            // getDeclaredFields 获取所有的属性
            Field[] fds = c.getDeclaredFields();

            for (Field f : fds) {
                System.out.println("该属性的名称:" + f.getName() + ",修饰符：" + Modifier.toString(f.getModifiers()) + ",类型："
                        + f.getType().getName());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 获得类实现的接口
    public void getInterfaces(String className) {
        try {
            Class cl = Class.forName(className);
            Class[] ifs = cl.getInterfaces();
            for (Class c : ifs) {
                System.out.println("该类实现的接口名字为：" + c.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取类的修饰符
    public void getClassModifier(String className) {
        try {
            Class cl = Class.forName(className);
            int m = cl.getModifiers();
            System.out.println("该类的修饰符为:" + Modifier.toString(m));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获得类的构造函数
    public void getClassConstructor(String className) {
        try {
            // 获得类的对象
            Class cl = Class.forName(className);
            Constructor ctorlist[] = cl.getDeclaredConstructors();
            for (Constructor con : ctorlist) {
                System.out.print("这个构造函数的名字为：" + con.getName() + "(");
                Class cp[] = con.getParameterTypes();
                for (Class c : cp) {
                    System.out.print(c.getName() + ",");
                }
                System.out.println(")");
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }

    public void getClassMethods(String className) {
        try {
            Class cl = Class.forName(className);
            Method[] ms = cl.getDeclaredMethods();
            for (Method m : ms) {
                System.out.print("该类的方法  :" + " 返回值类型-->" + m.getReturnType() + "   ");
                System.out.print("方法名称：" + m.getName() + "(");
                Class cp[] = m.getParameterTypes();
                for (Class c : cp) {
                    System.out.print(c.getName() + ",");
                }
                System.out.println(")");
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }

    public Class getClass(String className) {
        Class cl = null;
        try {
            cl = Class.forName(className);
        } catch (Exception e) {
            System.err.println(e);
        }
        return cl;
    }

    public static void main(String[] args) {
        ReflectTest reflectTest = new ReflectTest();
        System.out.println("类名：" + reflectTest.getNameByClass());
        System.out.println("类名：" + reflectTest.getSuperClassBySubClass());
        System.out.println("类名：" + reflectTest.getClassByClassName("cn.chencq.reflect.Student"));
        reflectTest.getFieldNames("cn.chencq.reflect.Student");
        reflectTest.getInterfaces("cn.chencq.reflect.Student");
        reflectTest.getClassModifier("cn.chencq.reflect.Student");

        reflectTest.getClassConstructor("cn.chencq.reflect.Student");
        reflectTest.getClassMethods("cn.chencq.reflect.Student");

        // 无参数构造对象
        Class c = reflectTest.getClass("cn.chencq.reflect.Student");
        Student stu1 = null;
        try {
            stu1 = (Student) c.newInstance();
            stu1.SetName("chencq");
            stu1.SetSex("MAN");
            System.out.println(stu1.getSex());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        // 有参数构造对象
        Class c2 = reflectTest.getClass("cn.chencq.reflect.Student");
        Student stu2 = null;
        try {
            Constructor<?> con = c2.getDeclaredConstructor(String.class, String.class);
            stu2 = (Student) con.newInstance("chencq", "Man");
            System.out.println(stu2.getName());
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // 通过反射调用方法
        Student stu3 = new Student("test", "Women");
        Class<?> c3 = stu3.getClass();

        try {
            // getMethod()方法需要传入方法名，和参数类型
            Method m1 = c3.getMethod("getName");
            // invoke()表示调用的意思，需要传入对象和参数
            System.out.println("通过反射调用方法：" + m1.invoke(stu3));

            // getMethod()方法需要传入方法名，和参数类型
            Method m2 = c3.getMethod("SetName", String.class);
            // invoke()表示调用的意思，需要传入对象和参数
            m2.invoke(stu3, "test2");
            System.out.println("通过反射调用setName方法后:" + stu3.getName());

            // 定义要修改的属性
            Field f = c3.getDeclaredField("sex");
            // sex是私有属性,setAccessible()方法可以设置是否访问和修改私有属性
            f.setAccessible(true);
            // 修改属性，传入要设置的对象和值
            f.set(stu3, "MAN");
            System.out.println("通过反射修改sex属性值后:" + stu3.getSex());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
